use serde2file::encrypt::Aes256GcmEncryptUtil;
use serde::{Deserialize, Serialize};

use serde2file::prelude::*;

#[allow(dead_code)]
#[derive(Debug, Serialize, Deserialize, Default, PartialEq, Eq, Serde2File)]
#[serde2file(
    encrypt = "TestEncryptTool::encrypt",
    decrypt = "TestEncryptTool::decrypt",
    crypt_arg_type = "&'static str",
    dump_file_name = "test_data.json"
)]
struct TestData {
    id: String,
    name: String,
}
/// a encryption and decryption tools
#[allow(dead_code)]
struct TestEncryptTool;
impl Aes256GcmEncryptUtil for TestEncryptTool {
    type CryptArgType = &'static str;
    fn get_aes_key_nonce(extra: Option<Self::CryptArgType>) -> (String, String) {
        (
            format!("*)_#@{}!$=_^20230208)leb*$xz", extra.unwrap_or("140600")),
            "abc$hy%95599".into(),
        )
    }
}

/// Test serialization and encrypted storage to file
/// 测试序列化并加密存储到文件
#[test]
fn test_serde_file_extra() {
    let data = TestData {
        id: "01".into(),
        name: "hy".into(),
    };
    assert_eq!(
        "/tmp/test_data.json",
        data.dump2file_with_encrypt_arg("/tmp", Some("14H700")).unwrap()
    );
    let s_data = TestData::load_from_file_with_decrypt_arg("/tmp", Some("14H700")).unwrap();
    assert_eq!(data, s_data)
}

/// Test serialization and encrypted storage to file
/// 测试序列化并加密存储到文件
#[test]
fn test_serde_file() {
    let data = TestData {
        id: "01".into(),
        name: "hy".into(),
    };
    assert_eq!("/tmp/test_data.json", data.dump2file("/tmp").unwrap());
    let s_data = TestData::load_from_file("/tmp").unwrap();
    assert_eq!(data, s_data)
}

#[allow(dead_code)]
#[derive(Debug, Serialize, Deserialize, Default, PartialEq, Eq, Serde2File)]
#[serde2file(dump_file_name = "test_data2.json")]
struct TestData2 {
    id: String,
    name: String,
}

/// Test serialization and encrypted storage to file
/// 测试序列化并加密存储到文件
#[test]
fn test_serde_file_extra2() {
    let data = TestData2 {
        id: "01".into(),
        name: "hy".into(),
    };
    assert_eq!(
        "/tmp/test_data2.json",
        data.dump2file_with_encrypt_arg("/tmp", Some(())).unwrap()
    );
    let s_data = TestData2::load_from_file_with_decrypt_arg("/tmp", Some(())).unwrap();
    assert_eq!(data, s_data)
}

/// Test serialization and encrypted storage to file
/// 测试序列化并加密存储到文件
#[test]
fn test_serde_file2() {
    let data = TestData2 {
        id: "01".into(),
        name: "hy".into(),
    };
    assert_eq!("/tmp/test_data2.json", data.dump2file("/tmp").unwrap());
    let s_data = TestData2::load_from_file("/tmp").unwrap();
    assert_eq!(data, s_data)
}

#[allow(dead_code)]
#[derive(Debug, Serialize, Deserialize, Default, PartialEq, Eq, Serde2File)]
#[serde2file(
    encrypt = "TestEncryptTool2::encrypt",
    decrypt = "TestEncryptTool2::decrypt",
    dump_file_name = "test_data3.json"
)]
struct TestData3 {
    id: String,
    name: String,
}
/// a encryption and decryption tools
#[allow(dead_code)]
struct TestEncryptTool2;
impl Aes256GcmEncryptUtil for TestEncryptTool2 {
    type CryptArgType = ();
    fn get_aes_key_nonce(_extra: Option<Self::CryptArgType>) -> (String, String) {
        (
            "*)_#@140600!$=_^20230208)leb*$xz".into(),
            "abc$hy%95599".into(),
        )
    }
}

/// Test serialization and encrypted storage to file
/// 测试序列化并加密存储到文件
#[test]
fn test_serde_file3() {
    let data = TestData3 {
        id: "01".into(),
        name: "hy".into(),
    };
    assert_eq!("/tmp/test_data3.json", data.dump2file("/tmp").unwrap());
    let s_data = TestData3::load_from_file("/tmp").unwrap();
    assert_eq!(data, s_data)
}

// 使用函数个性化文件名

#[allow(dead_code)]
#[derive(Debug, Serialize, Deserialize, Default, PartialEq, Eq, Serde2File)]
#[serde2file(
    encrypt = "TestEncryptTool2::encrypt",
    decrypt = "TestEncryptTool2::decrypt",
    dump_file_name = "test_data3.json",
    file_name_getter = "get_file_name",
    file_name_getter_arg_type = "String"
)]
struct TestData4 {
    id: String,
    name: String,
}

fn get_file_name(sys_root:&str,extra:Option<String>) -> DumpResult<String>{
    Ok(format!("{sys_root}/{}",extra.unwrap()))
}

/// Test serialization and encrypted storage to file
/// 格式个性化文件名称
#[test]
fn test_serde_file4() {
    let data = TestData4 {
        id: "01".into(),
        name: "hy".into(),
    };
    let file_name_arg = String::from("14H.json");
    assert_eq!(format!("/tmp/{file_name_arg}"), data.dump2file_with_path("/tmp",Some(String::from("14H.json"))).unwrap());
    let s_data = TestData4::load_from_file_with_path("/tmp",Some(String::from("14H.json"))).unwrap();
    assert_eq!(data, s_data)
}

